import os
from flask import Flask, request, g, current_app
from flask_mqtt import Mqtt
import queue
import threading
import binascii

from .config import DevelopmentConfig, ProductionConfig, Config
from src.core import ack_publish


def create_app(env=None):
    """应用工厂函数"""
    app = Flask(__name__, template_folder=r'D:\Users\123\PycharmProjects\mqtt\templates',
                static_folder=r'D:\Users\123\PycharmProjects\mqtt\static')

    # 确定环境配置
    if not env:
        env = os.getenv('FLASK_ENV', 'development')

    # 加载配置
    config_map = {
        'development': DevelopmentConfig,
        'production': ProductionConfig,
    }
    if env not in config_map:
        raise ValueError(f"Unknown environment: {env}")

    app.config.from_object(config_map[env])

    # ✨ 初始化日志配置
    Config.init_logging()

    # ✨ 设置应用logger的日志级别
    app.logger.setLevel(app.config['LOG_LEVEL'])

    # 加载实例配置
    app.config.from_pyfile('config.py', silent=True)

    # 从环境变量覆盖配置
    app.config.update({
        k: os.getenv(k.upper(), v) for k, v in app.config.items()
        if k not in app.config.get('PROTECTED_KEYS', [])
    })


    # 注册蓝图
    register_blueprints(app)

    # 注册MQTT回调
    register_mqtt_callbacks(app)

    # 注册请求钩子
    register_hooks(app)
    return app


def register_blueprints(app):
    """注册应用蓝图"""
    from routes.users import user_bp
    from routes.deives import devices
    from routes.iot_admin import iot_admin_bp
    from src.utils import error_bp

    app.register_blueprint(user_bp)
    app.register_blueprint(devices)
    app.register_blueprint(iot_admin_bp)
    app.register_blueprint(error_bp)


def register_mqtt_callbacks(app):
    """注册MQTT回调函数"""
    message_queue = queue.Queue()
    topic = "T/#"
    matt_ack = ack_publish.MQTTServer()
    mqtt_client = Mqtt(app)

    @mqtt_client.on_connect()
    def handle_connect(client, userdata, flags, rc):
        """连接回调函数"""
        if rc == 0:
            print('Connected successfully')
            # 订阅主题
            mqtt_client.subscribe(topic, qos=1)
        else:
            # 连接失败
            print('Bad connection. Code:', rc)

    def worker():
        while True:
            data = message_queue.get()
            # app.logger.info('Received message on topic: {topic} with payload: {payload}'.format(**data))
            matt_ack.deal_message(msg=data)
            message_queue.task_done()

    # 启动 10 个工作线程
    for _ in range(10):
        threading.Thread(target=worker, daemon=True).start()

    @mqtt_client.on_message()
    def handle_mqtt_message(client, userdata, message):
        """ 消息回调函数 """
        # 定义接受到的消息
        data = dict(
            # 主题
            topic=message.topic,
            # 内容
            payload=binascii.hexlify(message.payload).decode()  # 解码
        )
        message_queue.put(data)  # 将消息交给工作线程


def register_hooks(app):
    """注册全局请求钩子"""
    @app.before_request
    def log_request_info():
        """记录请求信息"""
        app.logger.info(
            f"Request: {request.method} {request.path} | "
            f"IP: {request.remote_addr} | "
            f"Params: {request.args.to_dict()}"
        )

        # 记录POST/PUT的JSON数据（可选）
        if request.method in ['POST', 'PUT'] and request.is_json:
            app.logger.debug(f"JSON Data: {request.get_json()}")

    @app.after_request
    def log_response_info(response):
        """记录响应信息"""
        app.logger.info(
            f"Response: {request.method} {request.get_data()} | "
            f"Status: {response.status_code} | "
            # f"Size: {len(response.data)} bytes"
        )
        return response

    @app.teardown_request
    def log_errors(exc):
        """记录异常信息"""
        if exc:
            app.logger.error(
                f"Error: {request.method} {request.path} | "
                f"Exception: {str(exc)}",
                exc_info=True
            )
